#pragma once
#ifndef _LINAL_ABSTRACT_SLAE_SOLVER_
#define _LINAL_ABSTRACT_SLAE_SOLVER_

//================================================================================================================================
//================================================================================================================================
// Стандартные
#include <limits>
// Локальные
#include "math/math.h"
#include "linal/vector.h"
#include "linal/csrmatrix.h"
#include "core_global.h"

//================================================================================================================================
//================================================================================================================================
namespace linal
{
    /// Базовый класс для решателя СЛАУ.
    class CORE_EXPORT SLAESolver
    {
    public:
        SLAESolver() : m_MaxNumOfIter(std::numeric_limits<int>::max()), m_SufficientResidual(std::numeric_limits<double>::epsilon()) {}
        SLAESolver(int max_num_of_iter, double sufficient_residual) : m_MaxNumOfIter(max_num_of_iter), m_SufficientResidual(sufficient_residual) {}
        virtual ~SLAESolver(){}

        /// Установка максимального числа итераций решателя.
        /// \sa SLAESolver::m_MaxNumOfIter.
        void setMaxNumOfIter(int max_num_of_iter) {m_MaxNumOfIter = max_num_of_iter;}

        /// Установка достаточного значения невязки.
        /// \sa SLAESolver::m_SufficientResidual
        void setSufficientResidual(double sufficient_residual) {m_SufficientResidual = sufficient_residual;}

        /// Решение СЛАУ с матрицей в разреженном строчном формате.
        /// \param matrix Матрица СЛАУ.
        /// \param f Правая часть СЛАУ.
        /// \param [in,out] x На входе - начальное приближение решения СЛАУ. На выходе - решение СЛАУ.
        /// \return Невязка решения.
        virtual double solve(const CSRMatrix &matrix, const Vector &f, Vector &x) = 0;

        /// Решение СЛАУ с матрицей в разреженном строчном формате c использование LU факторизации.
        /// \param matrix Матрица СЛАУ.
        /// \param f Правая часть СЛАУ.
        /// \param [in,out] x На входе - начальное приближение решения СЛАУ. На выходе - решение СЛАУ.
        /// \return Невязка решения.
        virtual double solveLU(const CSRMatrix &matrix, const Vector &f, Vector &x) = 0;

        /// Решение СЛАУ с матрицей в разреженном строчном формате c использование диагональной факторизации.
        /// \param matrix Матрица СЛАУ.
        /// \param f Правая часть СЛАУ.
        /// \param [in,out] x На входе - начальное приближение решения СЛАУ. На выходе - решение СЛАУ.
        /// \return Невязка решения.
        virtual double solveDi(const CSRMatrix &matrix, const Vector &f, Vector &x) = 0;

        /// Выделение памяти для вспомогательных векторов итерационного метода.
        //
        /// Для оптимизации работы с памятью вспомогательные вектора хранятся и в промежутках между
        /// решениями СЛАУ, а их размер меняется только по необходимости.
        virtual void adaptForSLAE(int dimension) = 0;

    protected:
        /// Максимальное число итераций, отведённое на решение СЛАУ.
        //
        /// Итерационный метод теоретически может искать решение бесконечно. Для исключения подобных ситуаций
        /// используется кретерий останова процесса поиска решения по числу итераций. После совершения определённого
        /// числа итераций процесс поиска прекращается в независимости от того было ли найдено решение. По умолчанию
        /// максимальное число итерациё равно 1000.
        int m_MaxNumOfIter;

        /// Достаточная невязка.
        //
        /// Если значение невязки становится меньше, чем данная величина, решение СЛАУ считается найденным. По умолчанию
        /// достаточной считается невязка 1e-6.
        double m_SufficientResidual;
    };
}

#endif // _LINAL_ABSTRACT_SLAE_SOLVER_
